﻿using System;
using System.Collections.Generic;
using System.Data.Services.Client;
using System.Linq;
using System.Net;
using Microsoft.Samples.ServiceHosting.PersonalWebSite;
using Microsoft.Samples.ServiceHosting.StorageClient;

namespace BackupObjects
{
    /// <summary>
    /// Reposity used to persist BackupObjectTag into Cloud.
    /// </summary>
    internal class BackupTagRepository
    : BaseTableRepository<BackupObjectTag, BackupObjectTagRow>
    {
        private const string BackupObjectTagName = "BackupObjectTag";

        public BackupTagRepository(int numRetries)
            : base(numRetries)
        {
        }

        public BackupTagRepository()
            : base()
        {

        }

        public override string TableName
        {
            get { return BackupObjectTagName; }
        }

        /// <summary>
        /// Gets a list of tags for the current backup obj.
        /// </summary>
        /// <param name="backupObjectId">The backup obj. id.</param>
        /// <returns>The list of tag ids for the given backup obj. id.</returns>
        public List<Guid> GetTagsId(Guid backupObjectId)
        {
            if (backupObjectId == default(Guid))
            {
                return new List<Guid>();
            }

            var query = DataServiceQuery().Where(item => item.BackupObjectId == backupObjectId);

            TableStorageDataServiceQuery<BackupObjectTagRow> dataServiceQuery =
                new TableStorageDataServiceQuery<BackupObjectTagRow>(query as DataServiceQuery<BackupObjectTagRow>, TableRetry);

            return dataServiceQuery
                .ExecuteWithRetries()
                .Select(item => item.TagId)
                .ToList();
        }


        /// <summary>
        /// Gets a list of backup obj for the current tag.
        /// </summary>
        /// <param name="tagId">The tag. id.</param>
        /// <returns>The list of backup obj ids for the given tag id.</returns>
        public List<Guid> GetBackupObjectsId(Guid tagId)
        {
            var query = DataServiceQuery().Where(item => item.TagId == tagId);

            TableStorageDataServiceQuery<BackupObjectTagRow> dataServiceQuery =
                new TableStorageDataServiceQuery<BackupObjectTagRow>(query as DataServiceQuery<BackupObjectTagRow>, TableRetry);

            return dataServiceQuery
                .ExecuteWithRetries()
                .Select(item => item.BackupObjectId)
                .ToList();
        }

        /// <summary>
        /// Delete all the backup obj. tag based on the backup obj. id.
        /// </summary>
        /// <param name="backupObjectId"></param>
        public void DeleteByBackupObjectId(Guid backupObjectId)
        {
            var tagsIds = GetTagsId(backupObjectId);

            var context = TableStorage.GetDataServiceContext();
            foreach (var tagId in tagsIds)
            {                
                var obj = (BackupObjectTagRow)Load(backupObjectId, tagId,context);

                context.DeleteObject(obj);                
            }
            context.SaveChanges();
        }

        /// <summary>
        /// Load an object based on the backup obj id and tag id.
        /// </summary>
        /// <param name="backupObjectId">The backup obj. id.</param>
        /// <param name="tagId">The tag id.</param>
        /// <returns>The obj. with the given ids.</returns>
        public BackupObjectTag Load(Guid backupObjectId, Guid tagId, TableStorageDataServiceContext context=null)
        {
            var query = DataServiceQuery(context).Where(
                    item =>
                            item.TagId == tagId
                            && item.BackupObjectId == backupObjectId);

            TableStorageDataServiceQuery<BackupObjectTagRow> dataServiceQuery =
                new TableStorageDataServiceQuery<BackupObjectTagRow>(query as DataServiceQuery<BackupObjectTagRow>, TableRetry);

            var items = dataServiceQuery
                .ExecuteWithRetries()
                .ToList();

            if (items == null || items.Count == 0)
            {
                return null;
            }

            return items.First();
        }

        /// <summary>
        /// Save the relachionship between backup object and tags.
        /// </summary>
        /// <param name="backupObject"></param>
        public void Save(BackupObject backupObject)
        {
            if (backupObject.TagIds == null) { return; }

            //Save each relachionship.
            foreach (var tagId in backupObject.TagIds)
            {
                Save(new BackupObjectTag()
                         {
                             BackupObjectId = backupObject.ID,
                             TagId = tagId
                         });
            }
        }
    }
}
